package cn.labbook.bluetooth.controller.PayController;

import cn.labbook.bluetooth.constant.AmmeterConstant;
import cn.labbook.bluetooth.constant.PayConstant;
import cn.labbook.bluetooth.entity.*;
import cn.labbook.bluetooth.entity.wxpay.WXPayment;
import cn.labbook.bluetooth.service.*;
import cn.labbook.bluetooth.util.TimeUtils;
import cn.labbook.bluetooth.util.weixin.pay.PayUtil;
import cn.labbook.bluetooth.util.weixin.pay.UUIDHexGenerator;
import cn.labbook.bluetooth.util.weixin.pay.XmlUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Controller
@Slf4j
public class WeiXinNativePaymentController {

    @Autowired
    private IServicePayService servicePayService;
    @Autowired
    private IServicePayCreateService servicePayCreateService;
    @Autowired
    private IAmmeterService ammeterService;
    @Autowired
    private IAdminService adminService;
    @Autowired
    private IConstantService constantService;

    private final String mch_id = "1491927112";//商户号
    private final String spbill_create_ip = "127.0.0.1";//终端IP
    private final String notify_url = "https://bluetooth.zoercn.com/bluetooth/weixin/native/paycallback";//通知地址
    private final String trade_type = "NATIVE";//交易类型
    private final String url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
    private final String key = "&key=zk123sqweqdsadZK9120392018490184"; // 商户支付密钥
    private final String appid = "wxafeeae8c758d838d";

    /**
     *
     * @param body  商品简单描述，该字段请按照规范传递。 例：腾讯充值中心-心悦会员充值
     * @return
     */
    @RequestMapping("/weixin/native/payment")
    @ResponseBody
    public JSONObject payment(@RequestParam(required = false) String body,String ammeterIds) throws Exception {
        JSONObject JsonObject = new JSONObject() ;
//        body = new String(body.getBytes("UTF-8"),"ISO-8859-1");
        String nonce_str = UUIDHexGenerator.generate();//随机字符串
        String today = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
        String code = PayUtil.createCode(8);
        String out_trade_no = mch_id + today + code;//商户订单号

        //创建预支付订单
        String[] split = ammeterIds.split(",");
        Double totalfee= 0.00;
        double aa=0.00;
        for(String ammeterId : split){
            Ammeter ammeter = ammeterService.getById(ammeterId);
            Admin admin = adminService.getById(ammeter.getAdminId());
            boolean flag = (admin.getPermission()==1);
            Constant serverPrice = constantService.getById("serverPrice");
            ServicePayCreate servicePayCreate = new ServicePayCreate();
            servicePayCreate.setAmmeterId(ammeterId);
            servicePayCreate.setCreateTime(new Date());
            servicePayCreate.setPayType(1);
            servicePayCreate.setServicePayId(out_trade_no);
            if(ammeter.getPayPrice()==0||!flag){
                servicePayCreate.setPayPrice(serverPrice.getV());
            }else{
                if(serverPrice.getV()>ammeter.getPayPrice()){
                    servicePayCreate.setPayPrice(serverPrice.getV());
                }else{
                    servicePayCreate.setPayPrice(ammeter.getPayPrice());
                }
            }
            totalfee += servicePayCreate.getPayPrice();
            BigDecimal bigDecimal = new BigDecimal(Double.toString(totalfee));
            aa = Double.parseDouble(bigDecimal.setScale(2, BigDecimal.ROUND_HALF_UP).toString());
            servicePayCreateService.save(servicePayCreate);
        }
        ServicePay servicePay = new ServicePay();
        servicePay.setServicePayId(out_trade_no);
        servicePay.setCreateTime(new Date());
        servicePay.setPayAmount(aa);
        servicePay.setPayStatus(PayConstant.NO);
        servicePayService.save(servicePay);

        WXPayment paymentPo = new WXPayment();
        paymentPo.setAppid(appid);
        paymentPo.setMch_id(mch_id);
        paymentPo.setNonce_str(nonce_str);
//        String newbody = new String(body.getBytes("ISO-8859-1"),"UTF-8");//以utf-8编码放入paymentPo，微信支付要求字符编码统一采用UTF-8字符编码
        paymentPo.setBody("智慧佐客-服务费");
        paymentPo.setOut_trade_no(out_trade_no);
        String s = String.valueOf((int) (totalfee * 100));
        paymentPo.setTotal_fee(s);
        paymentPo.setSpbill_create_ip(spbill_create_ip);
        paymentPo.setNotify_url(notify_url);
        paymentPo.setTrade_type(trade_type);
        // 把请求参数打包成数组
        Map<String, Object> sParaTemp = new HashMap();
        sParaTemp.put("appid", paymentPo.getAppid());
        sParaTemp.put("mch_id", paymentPo.getMch_id());
        sParaTemp.put("nonce_str", paymentPo.getNonce_str());
        sParaTemp.put("body",  paymentPo.getBody());
        sParaTemp.put("out_trade_no", paymentPo.getOut_trade_no());
        sParaTemp.put("total_fee",paymentPo.getTotal_fee());
        sParaTemp.put("spbill_create_ip", paymentPo.getSpbill_create_ip());
        sParaTemp.put("notify_url",paymentPo.getNotify_url());
        sParaTemp.put("trade_type", paymentPo.getTrade_type());
        // 除去数组中的空值和签名参数
        Map sPara = PayUtil.paraFilter(sParaTemp);
        String prestr = PayUtil.createLinkString(sPara); // 把数组所有元素，按照“参数=参数值”的模式用“&”字符拼接成字符串
        //MD5运算生成签名
        String mysign = PayUtil.sign(prestr, key, "utf-8").toUpperCase();
        paymentPo.setSign(mysign);
        //打包要发送的xml
        String respXml = XmlUtil.messageToXML(paymentPo);
        // 打印respXml发现，得到的xml中有“__”不对，应该替换成“_”
        respXml = respXml.replace("__", "_");
        String param = respXml;
        //String result = SendRequestForUrl.sendRequest(url, param);//发起请求
        String result = PayUtil.httpRequest(url, "POST", param);

        // 将解析结果存储在Map中
        Map map = new HashMap();
        InputStream in=new ByteArrayInputStream(result.getBytes());
        // 读取输入流
        SAXReader reader = new SAXReader();
        Document document = reader.read(in);
        // 得到xml根元素
        Element root = document.getRootElement();
        // 得到根元素的所有子节点
        List<Element> elementList = root.elements();
        for (Element element : elementList) {
            map.put(element.getName(), element.getText());
        }
        // 返回信息
        String return_code = map.get("return_code").toString();//返回状态码
        String return_msg = map.get("return_msg").toString();//返回信息
        String result_code = map.get("result_code").toString();//返回状态码

        //控制台打印
        if("SUCCESS".equals(return_code) && "SUCCESS".equals(result_code)){
            // 业务结果
            String prepay_id = map.get("prepay_id").toString();//返回的预付单信息
            String nonceStr = UUIDHexGenerator.generate();
            JsonObject.put("nonceStr", nonceStr);
            JsonObject.put("package", "prepay_id=" + prepay_id);
            Long timeStamp = System.currentTimeMillis() / 1000;
            JsonObject.put("timeStamp", timeStamp + "");
            String stringSignTemp = "appId=" + appid + "&nonceStr=" + nonceStr + "&package=prepay_id=" + prepay_id + "&signType=MD5&timeStamp=" + timeStamp;
            //再次签名
            String paySign = PayUtil.sign(stringSignTemp, key, "utf-8").toUpperCase();
            JsonObject.put("paySign", paySign);
            JsonObject.put("code_url", map.get("code_url"));
            JsonObject.put("out_trade_no", out_trade_no);
        }

        PayUtil.imgUrl(map.get("code_url").toString());
        return JsonObject;
    }


    /**
     * 预支付时填写的 notify_url ，支付成功后的回调接口
     * @param request
     */
    @RequestMapping("/weixin/native/paycallback")
    @ResponseBody
    public String paycallback(HttpServletRequest request) {
        log.info("进入微信native支付回调--------------------------------");
        try {
            Map<String, Object> dataMap = XmlUtil.parseXML(request);
            log.info(dataMap.toString());
            ServicePay servicePay = servicePayService.getById(dataMap.get("out_trade_no").toString());
            if(servicePay.getPayAmount()*100 == Double.parseDouble(dataMap.get("total_fee").toString())){
                if(servicePay.getPayStatus()!=null) {
                    if (dataMap.get("return_code").equals("SUCCESS")) {
//                        log.info("支付成功");
                        servicePay.setPayStatus(PayConstant.YES);
                    } else if (dataMap.get("return_code").equals("FAIL")) {
                        log.info("支付失败");
                        servicePay.setPayStatus(PayConstant.NO);
                    }
                    servicePay.setUserId(dataMap.get("openid").toString());
                }
                servicePay.setServicePayId(dataMap.get("out_trade_no").toString());
                servicePayService.updateById(servicePay);

            }
            //{"transaction_id":"4200000109201805293331420304","nonce_str":"402880e963a9764b0163a979a16e0002","bank_type":"CFT","openid":"oXI6G5Jc4D44y2wixgxE3OPwpDVg","sign":"262978D36A3093ACBE4B55707D6EA7B2","fee_type":"CNY","mch_id":"1491307962","cash_fee":"10","out_trade_no":"14913079622018052909183048768217","appid":"wxa177427bc0e60aab","total_fee":"10","trade_type":"JSAPI","result_code":"SUCCESS","time_end":"20180529091834","is_subscribe":"N","return_code":"SUCCESS"}
        } catch (Exception e) {
            log.error("支付回调错误",e);
        }
        return "<xml>\n" +
                "  <return_code><![CDATA[SUCCESS]]></return_code>\n" +
                "  <return_msg><![CDATA[OK]]></return_msg>\n" +
                "</xml>";
    }

    @RequestMapping("weixin/code")
    public String wxCode(Model model,String code_url){
        model.addAttribute("code_url",code_url);
        return "wxpay/wx.nativepay";
    }

    @RequestMapping("/weixin/native/check")
    @ResponseBody
    public JSONObject check(String outTradeNo) {
        JSONObject JsonObject = new JSONObject() ;
        try {
            ServicePay servicePay = servicePayService.getById(outTradeNo);
            if(servicePay!= null){
                if(servicePay.getPayStatus()==PayConstant.YES){
                    LambdaQueryWrapper<ServicePayCreate> lambda = new QueryWrapper<ServicePayCreate>().lambda();
                    lambda.eq(ServicePayCreate::getServicePayId,outTradeNo);
                    List<ServicePayCreate> list = servicePayCreateService.list(lambda);
                    for(ServicePayCreate bean : list){
                        Ammeter ammeter = ammeterService.getById(bean.getAmmeterId());
                        if(ammeter.getServerStatus()==AmmeterConstant.serverStatus.EXPIRE){
                            Date date = TimeUtils.addMonth(12, new Date());
                            ammeter.setServerTime(date);
                        }else{
                            Date date = TimeUtils.addMonth(12, ammeter.getServerTime());
                            ammeter.setServerTime(date);
                        }
                        ammeter.setServerStatus(AmmeterConstant.serverStatus.NOTEXPIRE);
                        ammeterService.updateById(ammeter);
                    }
                    JsonObject.put("msg","success");
                }else {
                    JsonObject.put("msg","fail");
                }
            }else{
                JsonObject.put("msg","fail");
            }
        } catch (Exception e) {
            log.error("支付查询错误",e);
        }
        return JsonObject;
    }
}
